package com.cskaoyan.javase.oop1._6constructor;

/**
 * 引例:
 * 创建一个教师类，有课程和年龄两个属性，行为是可以上课。
 * 现在我们需要创建以下对象：
 * 18岁的Java老师对象
 * 28岁的C++老师对象
 * 30岁的Python老师对象
 * ...
 * 按照之前我们的做法，需要先创建出对象，再进行成员变量的赋值。
 * 这样做如果只有一个两个对象还好，如果需要创建很多对象，就有点过于麻烦了。
 * 对象的属性，能不能"出厂"的时候就设定好呢？能不能灵活的在创建对象过程中,给成员变量赋值呢?
 * 有这种需求时，就需要，构造方法（constructor，也叫构造器）来完成了。
 *
 * 构造器(也叫构造方法)它是定义在类体当中的一种特殊的方法,它仍然是方法,但是很特殊,不是一般方法.
 *
 * 构造器的语法如下:
 * [访问权限修饰符] 类名(形参列表){
 *   // 构造方法体
 * }
 * 解释:
 *      1.访问权限修饰符我们还没有学习，这里我们默认它是public修饰的。
 *      2.类名的位置必须和当前类的类名完全一致。（类名是大驼峰的，这里也要大驼峰）
 *          构造方法是没有返回值的,也不需要返回值,构造方法中是不能使用return关键字.
 *          构造器的名字和当前类的名字必须保持一致,它不是返回值类型
 *      3.形参列表可以为空，称之为无参构造方法，简称无参构造。当然也可以有参数，是为有参构造。
 *      4.构造方法体，和一般方法类似，可以写语句。
 *
 * 构造器的作用:
 *      在Java中使用new关键字，创建对象，必然调用构造方法。
 *      构造器的作用是在new对象过程中,用来给成员变量赋值的。
 *      构造器的作用不是创建对象,而是赋值!!!!!
 *
 * 我们发现一个类中,如果没有定义任何构造器,仍然可以使用无参构造器来new对象,来给成员变量赋值
 * 这说明:
 * (非常重要)在任何Java类中,如果类中没有直接定义构造器,那就提供默认的无参构造器
 * 默认无参格式如下:
 * public 类名(){}
 *
 *
 * 无参构造器不能用来完成成员变量的赋值,所以如果有对属性赋值的需求,那就定义有参构造器.
 * 在具体讲解有参构造器的标准格式前,需要知道:
 *      构造器是在new对象过程中的一种赋值手段,因为构造器的方法体和成员方法的方法体类似,都有this传参
 *          既然构造方法中都有this传参了,都有当前对象了
 *          说明构造器执行时,对象早就创建完了,对象已经有了,构造器不是用来创建对象
 *     于是有参构造器的标准格式如下:
 *          public 类名(数据类型 成员变量1,数据类型 成员变量2,....){
 *              this.成员变量1 = 成员变量1;
 *              ...
 *          }
 *
 *
 * 注意事项:
 *      1.类中可能有多个构造器,它们的名字是一样的,但是形参列表不同,这就是方法的重载语法.
 *      所以在类中定义构造器
 *      只要是符合方法重载,都可以定义
 *
 *      2.如果类中已经明确提供了一个构造器,那么就不会再提供默认无参了.
 *      扩展:
 *          a.建议在定义一个可能创建对象的类时,手动加上无参构造,这是一个好习惯.
 *          b.(非常重要)Java中任何类都有构造器
 *          如果说类中有一个结构是必须要有的,那就是构造器
 *          以上说法虽然很绝对,但是正确的
 *
 *      3.(最重要的特点)构造器的作用是给成员变量赋值,不是创建对象
 *      而且构造器给成员变量的赋值一定是稳定可靠的
 *      使用标准格式构造器赋值,最终成员变量的赋值结果一定是构造器中的赋值结果.
 *      "永远可以相信构造器"
 *      这是因为在new对象过程中,所有的赋值手段中,
 *      构造器的代码是最后执行的
 *      所以它的赋值肯定是最终结果
 *
 *      4.标准格式的构造器
 *      指的是: 无参 public 类名(){}
 *      有参
 *      public 类名(数据类型 成员变量1,数据类型 成员变量2,....){
 *             this.成员变量1 = 成员变量1;
 *             ...
 *      }
 *      idea提供了自动生成标准格式构造器的快捷键:
 *      Alt + Insert/Ins /Fn
 *
 *      5.构造器的调用也是不同于一般方法的。它是在new对象过程中，由JVM自己去调用的
 *          程序员是没有办法主动来调用某个构造方法的
 *          但是我们仍然可以通过"new 类名（实参列表）"来表示调用某个构造器完成赋值。
 *
 * @since 11:19
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {

        // 18岁的Java老师对象
        Teacher javaTeacher = new Teacher();
        javaTeacher.course = "Java";
        javaTeacher.age = 18;
        javaTeacher.teach();
        // 28岁的C++老师对象
        Teacher cppTeacher = new Teacher();
        cppTeacher.course = "C++";
        cppTeacher.age = 28;
        cppTeacher.teach();
        // 30岁的Python老师对象
        Teacher pythonTeacher = new Teacher();
        pythonTeacher.course = "Python";
        pythonTeacher.age = 30;
        pythonTeacher.teach();
        System.out.println("----------------");
        // 50岁的物理老师 
        Teacher physicalTeacher = new Teacher("物理",50);
        physicalTeacher.teach();
        Teacher mathTeacher = new Teacher("数学", 30);
        mathTeacher.teach();


        // 任何类都有构造器
        A a = new A();
    }
}

class A{

}

class Teacher {
    String course;
    int age;
    String name;

    public void teach() {
        System.out.println("这位" + age + "岁的" + course + "老师,正在给学生上课!");
    }

    /*
        这是一个普通方法,static修饰的方法
        这个方法中的Teacher是返回值类型,表示方法会返回一个Teacher对象
      */
    public static Teacher test(int a) {
        Teacher t = new Teacher();
        return t;
    }

    // 无参构造器
    public Teacher() {
    }

    // 定义双参构造器给course和age赋值
    public Teacher(String course, int age) {
        this.course = course;
        this.age = age;
    }

    // 单参构造器,只给age赋值
    public Teacher(int age){
        this.age = age;
    }

    // 单参构造器,只给course赋值
    public Teacher(String course){
        this.course = course;
    }

    // 单参构造器,只给name赋值,肯定不行 形参名不同 不算方法的重载
    // public Teacher(String name){
    //     this.name = name;
    // }

    // 可变参数构造器是允许,但是没有意义(因为类中的成员变量个数肯定是固定的) 不要这么做
    // public Teacher(int... a){}
}